import router, { asyncRoutes } from '@/router'
import store from '@/store'
// 虚拟进度条  NProgress.start()  .done() 结束进度条
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css'
import getPageTitle from '@/utils/get-page-title'

// 登录页面 不需要登录就可以访问，
// 白名单 ： 项目里面 不需要token，不需要登录既可以看见的页面  注册页  登录页面  404 等
const whiteList = ['/login']
// 判断一个元素 在不在 数组里面
//  arr.includes(xxx)    arr.indexOf(xxx) === -1

// 路由守卫， 2个函数---钩子函数， 在进入页面开始的时候自动执行
router.beforeEach(async(to, from, next) => {
  document.title = getPageTitle(to.meta.title)
  NProgress.start()
  const token = store.state.user.token
  // console.log(token)
  // next()
  // 路由跳转判断， 先看有没有登录 （就是看有没有token值）
  if (token) {
    console.log(11, to)
    // if (to.path === '/login') {
    if (whiteList.includes(to.path)) {
      // 如果已经登录成功，还要去登录页面，用户体验就不好，应该直接给他跳转到首页
      next('/')
      NProgress.done()
    } else {
      // 这个地方就是 有token，并且访问的是一些需要权限的页面， 代码执行的方法
      // this.$store
      // 这里必须要加await， 因为不加的话，这个代码就不会等请求返回的结果，直接走了next，代码逻辑就不对
      // 正常的逻辑应该是， 等getuserInfo这个接口成功或者失败以后，在才走下面的next()  await会让代码中断，等待

      // 如果获取到了userInfo的数据，就不要再发送请求了 ---- 怎么样知道请求成功了 ---
      // 请求成功做了什么事情？ 将userInfo的数据放到了vuex里面去了， 随便找请求成功后，对象的一个属性，一般用id
      if (!store.state.user.userInfo.id) {
        // 如果没有发过请求，第一次进入页面，跳转路由的时候，执行这个if条件里面的代码
        // 一个异步请求，加上了await以后，有没有返回值，取决于异步方法里面，有没有return
        const res = await store.dispatch('user/getUserInfoAction') // 这个方法定义在 user模块里，方法在actions里面
        console.log('用户详细信息接口的返回值： ', res) // 得到当前用户有哪些页面权限，是数组，然后再去和asyncRoutes 进行对比在过滤

        // 添加动态路由规则表的时候，把asyncRoutes全量路由表先根据 服务器的返回值res 过滤一遍
        // 在50个元素里面asyncRoutes筛选 出来 2个元素
        const filterRoutes = asyncRoutes.filter(item => {
          // console.log(item.children[0].name)
          const currentName = item.children[0].name
          // [1,2,3,4,5,6,]  currentName = 1
          return res.includes(currentName)
        })

        console.log('过滤以后的数组：', filterRoutes)
        // 下面代码就是说 将* 匹配不到的路由，添加到所有路由规则的最后面去
        // 下面路由不能放在中间
        // state.menuList = [...constantRoutes, ’之前的*号路由在中间‘ ...payload]
        filterRoutes.push({ path: '*', redirect: '/404', hidden: true })

        // 我们的动态路由就添加在下面这里
        // 下面代码写完只有， 动态路由在内存里面，没有响应式的更新到左侧菜单
        // 为什么要在这里动态添加路由呢？ 因为上面有请求，返回的值里面有用户具有的一些权限数组列表
        // 可以将asyncRoutes 这个数组，进行过滤， 比如说asyncRoutes数组里面有50个元素，就是50个页面
        // 用户登录返回对应的权限以后， 在50个元素里面筛选，然后再动态加进去
        // console.log('如果不确定代码有没有走这里来，就写个特殊的lig打印')
        // 动态添加的路由，左侧的菜单是看不见的，要测试的话，就手动输入地址
        // router.addRoutes(asyncRoutes) // 等下写代码，就会有一个 filter 过滤的意思
        router.addRoutes(filterRoutes)

        // 上面的代码加载完了以后，只会在内存里面出现，要访问页面，只能手动输入地址
        // 想让左侧的菜单动态发生改变，就可以将asyncRoutes ，添加到vuexc里面去，修改vuex里面的menulist
        // store.commit('menu/setMenuList', asyncRoutes)
        store.commit('menu/setMenuList', filterRoutes)

        // 如果当前页面是动态添加的路由，在当前页面刷新的时候，要么是白屏，要么是调到首页
        next({
          ...to, // 动态添加的路由，重新在进入一遍
          replace: true // 将重新调整的动态路由的历史，不要加入到历史记录里面
        })
      } else {
        next()
      }

      // 下面代码是 路由通过，放行的时候， 必须是上一步请求成功或者失败，请求完成了，才能走下一步
      // next()

      //  await 就是把下面的 .then的语法 给 简写了， 形式上是同步的写法，本质上还是异步，会等待，
      // 和then里面的回调函数 一样
      // store.dispatch('user/getUserInfoAction').then(() => {
      //   next()
      // })
    }
  } else {
    // 没有登录过的逻辑 （用户通过一些地址栏，强行跳转到其他页面，我们应该有个拦截的操作）
    if (whiteList.includes(to.path)) {
      next()
    } else {
      next('/login')
      NProgress.done()
    }
  }
})

// 进入页面以后执行的钩子函数 afterEach
// afterEach 并不一定都会执行， 如果在进入的beforeEach钩子函数里面
// 通过next('参数') 跳转到了其他页面(将正常的跳转方向给他改变了)，这个afterEach就不会执行
router.afterEach(() => {
  NProgress.done()
})

// 请你描述一下路由守卫？
